package com.gyy.modbus4j;

import com.serotonin.modbus4j.ModbusFactory;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
import com.serotonin.modbus4j.msg.*;

import java.util.Arrays;

/**
 * @Author gmd
 * @Description modbus通讯，使用modbus4j框架往slave从机写数据
 * @Date 2021-12-16 15:03:50
 */
public class Modbus4jWrite {

    public static ModbusFactory modbusFactory = new ModbusFactory();


    /**
     * 获取tcpMaster
     */
    public static ModbusMaster getMaster() throws Exception {
        IpParameters params = new IpParameters();
        params.setHost("127.0.0.1");
        params.setPort(502);

        ModbusMaster tcpMaster = modbusFactory.createTcpMaster(params, false);
        tcpMaster.init();
        return tcpMaster;
    }

    /**
     * 往指定的Coil（0x01）写入数据
     *
     * @param slaveId     从机ID
     * @param writeOffset 位置
     * @param writeValue  值
     */
    public static void writeCoil(int slaveId, int writeOffset, boolean writeValue) throws Exception {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilRequest request = new WriteCoilRequest(slaveId, writeOffset, writeValue);
        // 发送请求并获取响应对象
        WriteCoilResponse response = (WriteCoilResponse) tcpMaster.send(request);

        System.out.println("向Coil线圈（0x01）写入布尔值。点位：" + writeOffset + "，布尔值：" + writeValue + "，是否成功：" + response.isWriteValue());
    }


    /**
     * 往指定的Coil（0x01）批量写入数据
     *
     * @param slaveId     从机ID
     * @param startOffset 开始位置
     * @param bData       批量结果值
     */
    public static void writeCoils(int slaveId, int startOffset, boolean[] bData) throws Exception {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求
        WriteCoilsRequest request = new WriteCoilsRequest(slaveId, startOffset, bData);
        // 发送请求并获取响应对象
        WriteCoilsResponse response = (WriteCoilsResponse) tcpMaster.send(request);

        System.out.println("向Coil线圈（0x01）批量写入布尔值。开始点位：" + startOffset + "，布尔值：" + Arrays.toString(bData) + "，是否成功：" + !response.isException());
    }


    /**
     * 往指定的HoldingRegister（0x03）写入数据
     *
     * @param slaveId     从机ID
     * @param writeOffset 位置
     * @param writeValue  结果值
     */
    public static void writeRegister(int slaveId, int writeOffset, short writeValue) throws Exception {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求对象
        WriteRegisterRequest request = new WriteRegisterRequest(slaveId, writeOffset, writeValue);
        WriteRegisterResponse response = (WriteRegisterResponse) tcpMaster.send(request);

        System.out.println("向HoldingRegister寄存器（0x03）写入数据。点位：" + writeOffset + "，数据：" + writeValue + "，是否成功：" + !response.isException());
    }


    /**
     * 往指定的HoldingRegister（0x03）批量写入数据
     *
     * @param slaveId     从机ID
     * @param startOffset 开始位置
     * @param sData       批量结果值
     */
    public static void writeRegisters(int slaveId, int startOffset, short[] sData) throws Exception {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 创建请求对象
        WriteRegistersRequest request = new WriteRegistersRequest(slaveId, startOffset, sData);
        // 发送请求并获取响应对象
        ModbusResponse response = tcpMaster.send(request);

        System.out.println("向HoldingRegister寄存器（0x03）写入数据。开始点位：" + startOffset + "，数据：" + Arrays.toString(sData) + "，是否成功：" + !response.isException());
    }

    /**
     * 往指定的HoldingRegister（0x03）写入指定类型的数据
     *
     * @param slaveId  从机ID
     * @param offset   位置
     * @param value    结果值
     * @param dataType 数据类型
     */
    public static void writeHoldingRegister(int slaveId, int offset, Number value, int dataType) throws Exception {
        // 获取master
        ModbusMaster tcpMaster = getMaster();
        // 类型
        BaseLocator<Number> locator = BaseLocator.holdingRegister(slaveId, offset, dataType);
        tcpMaster.setValue(locator, value);
        System.out.println("向HoldingRegister寄存器（0x03）写入" + DataType.getJavaType(dataType).getSimpleName() + "类型数据。点位：" + offset + "，数据：" + value.toString());
    }


    public static void main(String[] args) throws Exception {
        //writeCoil(1, 0, true);
        writeCoils(1, 0, new boolean[]{true, false, true, false, false, true, false, false, false, true});
        // writeRegister(1, 0, (short) 1234);
        // writeRegisters(1, 0, new short[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10});
        //writeHoldingRegister(3, 4, 10.123f, DataType.FOUR_BYTE_FLOAT);

    }

}